<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\WorkRoom\Queue;

use EasyWeChat\Work\Application;
use Hyperf\AsyncQueue\Annotation\AsyncQueueMessage;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Utils\Codec\Json;
use MoChat\App\Corp\Contract\CorpContract;
use MoChat\App\Corp\Utils\WeWorkFactory;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;

/**
 * 企业微信-同步微信客户群列表
 * Class SyncListQueue.
 */
class SyncListQueue
{
    /**
     * @Inject
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var CorpContract
     */
    private $corpService;

    /**
     * @var WorkEmployeeContract
     */
    private $workEmployeeService;

    /**
     * @var WeWorkFactory
     */
    private $weWorkFactory;

    /**
     * @var Application
     */
    private $weWorkApp;

    /**
     * @var LoggerFactory
     */
    private $loggerFactory;

    /**
     * @AsyncQueueMessage(pool="room")
     * @param int $corpId 企业授信ID
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function handle(int $corpId): void
    {
        $this->loggerFactory = $this->container->get(LoggerFactory::class);
        $this->logger = $this->loggerFactory->get(__CLASS__);
        $this->corpService = $this->container->get(CorpContract::class);
        $this->workEmployeeService = $this->container->get(WorkEmployeeContract::class);
        $this->weWorkFactory = $this->container->get(WeWorkFactory::class);

        try {
            $this->logger->debug(sprintf('同步客户群列表开始，企业ID:[%s]', (string) $corpId));
            $this->weWorkApp = $this->weWorkFactory->getContactApp($corpId);

            // 应用可见范围人数小于1000的企业直接查询，应用可见范围大于1000人的企业，每次查询500个员工为群主的群
            $employeeCount = $this->workEmployeeService->countWorkEmployeeByCorpId($corpId);
            if ($employeeCount === 0) {
                return;
            }

            if ($employeeCount < 1000) {
                $this->syncRoomList($corpId);
                return;
            }

            $pageTotal = ceil($employeeCount / 500);
            for ($page = 1; $page <= $pageTotal; ++$page) {
                $options = [
                    'page' => $page,
                    'perPage' => 500,
                ];

                $employees = $this->workEmployeeService->getWorkEmployeeList(['corp_id' => $corpId], ['wx_user_id'], $options);
                if (empty($employees['data'])) {
                    return;
                }

                $employeeUserIds = array_column($employees['data'], 'wxUserId');
                $this->syncRoomList($corpId, $employeeUserIds);
            }
        } catch (\Throwable $e) {
            $this->logger->error(sprintf('同步客户群列表失败，错误消息：%s', $e->getMessage()));
            $this->logger->error($e->getTraceAsString());
        }
    }

    /**
     * 获取同步群列表.
     */
    private function syncRoomList(int $corpId, array $userIdList = [], int $limit = 500, string $cursor = '')
    {
        $roomListParams = [
            'status_filter' => 0,
            'limit' => 500,
        ];

        if (! empty($userIdList)) {
            $roomListParams['owner_filter']['userid_list'] = $userIdList;
        }

        if ($cursor !== '') {
            $roomListParams['cursor'] = $cursor;
        }

        $roomListResult = $this->weWorkApp->external_contact->getGroupChats($roomListParams);

        if ($roomListResult['errcode'] != 0) {
            $this->logger->error(sprintf('%s [%s] 请求数据：%s 响应结果：%s', '请求企业微信客户群列表错误', date('Y-m-d H:i:s'), Json::encode($roomListParams), Json::encode($roomListResult)));
            return;
        }

        if (empty($roomListResult['group_chat_list'])) {
            return;
        }

        $this->syncRoomDetail($corpId, $roomListResult['group_chat_list']);

        if (isset($roomListResult['next_cursor']) && ! empty($roomListResult['next_cursor'])) {
            $this->syncRoomList($corpId, $userIdList, $limit, $roomListResult['next_cursor']);
        }
    }

    /**
     * 同步群详情.
     */
    private function syncRoomDetail(int $corpId, array $roomList)
    {
        $syncDetailQueue = make(SyncDetailQueue::class);
        foreach ($roomList as $room) {
            $syncDetailQueue->handle($corpId, $room);
        }
    }
}
